package main;

import javax.swing.*;

import main.Equipe;

import network.PingListener;
import network.ServerSocket;

import main.composantesJeu.Jeu;
import main.composantesJeu.Manche;
import main.composantesJeu.Partie;
import main.objet.Balle;
import main.objet.Joueur;
import main.objet.ObjetControlable;
import main.objet.Joueur.Cote;
import main.objet.Joueur.Service;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.*;
import java.io.IOException;
import java.util.Iterator;

@SuppressWarnings("serial")
public class ControleurJeu extends JPanel implements KeyListener {
    ServerSocket socket;
    Cadre fenetre;
    Partie partie;
    Timer timer;
    Equipe equipe1;
    Equipe equipe2;
    Joueur joueur1;
    Joueur joueur2;
    Joueur joueur3;
    Joueur joueur4;
    Balle balle;
    JLabel direction;
    JPanel indications;

    boolean up = false;
    boolean down = false;
    boolean left = false;
    boolean right = false;
    boolean service = false;

    Joueur joueur = joueur1;

    ControleurJeu() throws IOException {
	/*
	 * this.ardoise = new Cadre(); this.ardoise.setPreferredSize(new
	 * Dimension(600, 400)); this.ardoise.setForeground(getBackground());
	 * this.direction = new JLabel(" "); this.indications = new JPanel();
	 * this.joueur1 = new Joueur(); this.balle = new Balle();
	 * indications.setLayout(new GridLayout(1, 1));
	 * indications.add(direction); setLayout(new BorderLayout(5, 5));
	 * add(indications, BorderLayout.NORTH); add(ardoise,
	 * BorderLayout.CENTER); ardoise.addObjet(joueur1);
	 * ardoise.addObjet(balle);
	 */

	// this.fenetre = fenetre;
	// this.joueur = joueur;
	// addKeyListener (this);
	/*
	 * timer = createTimer(); timer.start (); joueur.setPosition(50,50);
	 * joueur.setVitesse(0,0); balle.setPosition(30, 10, 20);
	 * balle.setVitesse(8, 3, 10); this.dessinerTerrain();
	 */
	super();
	addKeyListener(this);

	socket = new ServerSocket();
	this.joueur1 = new Joueur(Joueur.Cote.GAUCHE);
	this.joueur2 = new Joueur(Joueur.Cote.GAUCHE);
	this.joueur3 = new Joueur(Joueur.Cote.DROITE);
	this.joueur4 = new Joueur(Joueur.Cote.DROITE);
	this.equipe1 = new Equipe(this.joueur1, this.joueur2);
	this.equipe2 = new Equipe(this.joueur3, this.joueur4);
	this.balle = new Balle();
	joueur1.setSocket(socket.getListeClientConnectes().get(0));

	for (int i = 0; i < socket.getListeClientConnectes().size(); i++)
	    socket.getListeClientConnectes().get(i).ajouterListener(
		    new PingListener(socket));

	socket.ajouterListener(new PingListener(joueur1.getSocket()));
	socket.ajouterListener(new PingListener(joueur2.getSocket()));
	socket.ajouterListener(new PingListener(joueur3.getSocket()));
	socket.ajouterListener(new PingListener(joueur4.getSocket()));
	socket.ajouterListener(new PingListener(balle.getSocket()));

	fenetre = new Cadre();
	direction = new JLabel("eee");
	indications = new JPanel();
	indications.setLayout(new GridLayout(1, 1));
	indications.add(direction);
	setLayout(new BorderLayout(5, 5));
	add(indications, BorderLayout.NORTH);
	add(fenetre, BorderLayout.CENTER);

    }

    public Cadre getFenetre() {
	return fenetre;
    }

    public void LancerDemo() {

	// this.controleur = new ControleurJeu(this.fenetre, this.joueur1);

	partie = new Partie(new Manche(new Jeu()));

	joueur1 = new Joueur(Joueur.Cote.GAUCHE);
	joueur1.setNumJoueur(1);
	joueur2 = new Joueur(Joueur.Cote.GAUCHE);
	joueur2.setNumJoueur(2);
	joueur3 = new Joueur(Joueur.Cote.DROITE);
	joueur3.setNumJoueur(3);
	joueur4 = new Joueur(Joueur.Cote.DROITE);
	joueur4.setNumJoueur(4);
	equipe1 = new Equipe(this.joueur1, this.joueur2);
	joueur1.setEquipe(this.equipe1);
	joueur2.setEquipe(this.equipe1);
	equipe2 = new Equipe(this.joueur3, this.joueur4);
	joueur3.setEquipe(this.equipe2);
	joueur4.setEquipe(this.equipe2);
	balle = new Balle();

	joueur = joueur1;
	fenetre.partie = partie;
	fenetre.requestFocus();
	fenetre.addObjet(joueur1);
	fenetre.addObjet(joueur2);
	fenetre.addObjet(joueur3);
	fenetre.addObjet(joueur4);
	fenetre.addObjet(balle);
	joueur1.setPosition(50, 150);
	joueur2.setPosition(100, 250);
	joueur3.setPosition(450, 150);
	joueur4.setPosition(450, 250);
	joueur1.setService(Joueur.Service.SERVICE_HAUT);
	// joueur1.setVitesse(0,0);
	balle.setPosition(30, 10, 20);
	balle.setVitesse(8, 3, 10);
	timer = createTimer();
	timer.start();
	// this.fenetre.dessinerTerrain();
    }

    public void arreterDemo() {
	socket.enleverListener(joueur1.getListener());
	socket.enleverListener(joueur2.getListener());
	socket.enleverListener(joueur3.getListener());
	socket.enleverListener(joueur4.getListener());
	socket.enleverListener(balle.getListener());
    }

    // M�thode renvoyant un timer pr�t � d�marrer
    private Timer createTimer() {
	// Cr�ation d'une instance de listener
	// associ�e au timer
	ActionListener action = new ActionListener() {
	    // M�thode appel�e � chaque tic du timer
	    public void actionPerformed(ActionEvent event) {

		// fenetre.controleur.notifier();
		update();
		fenetre.repaint();

	    }
	};

	// Cr�ation d'un timer qui g�n�re un tic
	// chaque 500 milli�me de seconde
	return new Timer(100, action);
    }

    public void gererPoint() {

	boolean point = false;
	if ((balle.getOut() == true) & (balle.getRebond() != 2)) {
	    if (equipe1.getFrappe()) {
		partie.getLastManche().getLastJeu().incPointageEquipe2();
		equipe1.setFrappe(false);
	    } else {
		partie.getLastManche().getLastJeu().incPointageEquipe1();
		equipe2.setFrappe(false);
	    }
	    point = true;
	    balle.setOut(false);
	    balle.setRebond(0);
	}

	if (balle.getRebond() == 2) {
	    if (equipe1.getFrappe()) {
		partie.getLastManche().getLastJeu().incPointageEquipe1();
		equipe1.setFrappe(false);
	    } else {
		partie.getLastManche().getLastJeu().incPointageEquipe2();
		equipe2.setFrappe(false);
	    }
	    point = true;
	    balle.setOut(false);
	    balle.setRebond(0);
	}

	if (point) {

	    if ((partie.getLastManche().getLastJeu().getPointageEquipe1() == 50)
		    | (partie.getLastManche().getLastJeu().getPointageEquipe2() == 50)) {
		if ((partie.getLastManche().getNbJeuEquipe1() == 6)
			| (partie.getLastManche().getNbJeuEquipe1() == 6)) {
		    partie.addManche(new Manche(new Jeu()));
		    if (joueur1.getCote() == Cote.GAUCHE) {
			joueur1.setCote(Cote.DROITE);
			joueur2.setCote(Cote.DROITE);
			joueur3.setCote(Cote.GAUCHE);
			joueur4.setCote(Cote.GAUCHE);
		    } else {
			joueur1.setCote(Cote.GAUCHE);
			joueur2.setCote(Cote.GAUCHE);
			joueur3.setCote(Cote.DROITE);
			joueur4.setCote(Cote.DROITE);
		    }
		} else {
		    partie.getLastManche().addJeu(new Jeu());

		}
		if ((joueur1.getService() == Service.SERVEUR_BAS)
			| (joueur1.getService() == Service.SERVEUR_HAUT)) {
		    joueur1.setService(Service.PAS_AU_SERVICE);
		    joueur3.setService(Service.SERVICE_HAUT);
		    joueur3.initPositionService();
		    joueur4.initPositionNormale('b');
		    joueur1.initPositionNormale('b');
		    joueur2.initPositionNormale('h');
		} else if ((joueur2.getService() == Service.SERVEUR_BAS)
			| (joueur2.getService() == Service.SERVEUR_HAUT)) {
		    joueur2.setService(Service.PAS_AU_SERVICE);
		    joueur4.setService(Service.SERVICE_HAUT);
		    joueur4.initPositionService();
		    joueur3.initPositionNormale('b');
		    joueur1.initPositionNormale('h');
		    joueur2.initPositionNormale('b');
		} else if ((joueur3.getService() == Service.SERVEUR_BAS)
			| (joueur3.getService() == Service.SERVEUR_HAUT)) {
		    joueur3.setService(Service.PAS_AU_SERVICE);
		    joueur2.setService(Service.SERVICE_HAUT);
		    joueur2.initPositionService();
		    joueur1.initPositionNormale('b');
		    joueur3.initPositionNormale('h');
		    joueur4.initPositionNormale('b');
		} else if ((joueur4.getService() == Service.SERVEUR_BAS)
			| (joueur4.getService() == Service.SERVEUR_HAUT)) {
		    joueur4.setService(Service.PAS_AU_SERVICE);
		    joueur1.setService(Service.SERVICE_HAUT);
		    joueur1.initPositionService();
		    joueur2.initPositionNormale('b');
		    joueur3.initPositionNormale('b');
		    joueur4.initPositionNormale('h');
		}
	    } else {
		if ((joueur1.getService() == Service.SERVEUR_BAS)
			| (joueur1.getService() == Service.SERVEUR_HAUT)) {
		    joueur1
			    .setService((joueur1.getService() == Service.SERVEUR_HAUT ? Service.SERVICE_BAS
				    : Service.SERVICE_HAUT));
		    joueur1.initPositionService();
		    joueur2
			    .initPositionNormale((joueur1.getService() == Service.SERVICE_HAUT ? 'b'
				    : 'h'));
		    joueur3.initPositionNormale('h');
		    joueur4.initPositionNormale('b');
		} else if ((joueur2.getService() == Service.SERVEUR_BAS)
			| (joueur2.getService() == Service.SERVEUR_HAUT)) {
		    joueur2
			    .setService((joueur2.getService() == Service.SERVEUR_HAUT ? Service.SERVICE_BAS
				    : Service.SERVICE_HAUT));

		    joueur2.initPositionService();
		    joueur1
			    .initPositionNormale((joueur2.getService() == Service.SERVICE_HAUT ? 'b'
				    : 'h'));
		    joueur3.initPositionNormale('b');
		    joueur4.initPositionNormale('h');
		} else if ((joueur3.getService() == Service.SERVEUR_BAS)
			| (joueur3.getService() == Service.SERVEUR_HAUT)) {
		    joueur3
			    .setService((joueur3.getService() == Service.SERVEUR_HAUT ? Service.SERVICE_BAS
				    : Service.SERVICE_HAUT));
		    joueur3.initPositionService();
		    joueur4
			    .initPositionNormale((joueur3.getService() == Service.SERVICE_HAUT ? 'b'
				    : 'h'));
		    joueur1.initPositionNormale('h');
		    joueur2.initPositionNormale('b');
		} else if ((joueur4.getService() == Service.SERVEUR_BAS)
			| (joueur4.getService() == Service.SERVEUR_HAUT)) {
		    joueur4
			    .setService((joueur4.getService() == Service.SERVEUR_HAUT ? Service.SERVICE_BAS
				    : Service.SERVICE_HAUT));
		    joueur4.initPositionService();
		    joueur3
			    .initPositionNormale((joueur4.getService() == Service.SERVICE_HAUT ? 'b'
				    : 'h'));
		    joueur1.initPositionNormale('b');
		    joueur2.initPositionNormale('h');
		}
	    }

	}

    }

    public void toucheAppuyee(int touche) {
	if (touche == KeyEvent.VK_UP) {
	    // direction.setText("up");
	    // if (!up)
	    // {
	    joueur.setVitesse(joueur.getVitesse().getX(), (joueur.getVitesse()
		    .getY() == 0 ? -8 : 0));
	    up = true;
	    // }
	} else if (touche == KeyEvent.VK_LEFT) {
	    // direction.setText("left");
	    // if (!left)
	    // {
	    joueur.setVitesse((joueur.getVitesse().getX() == 0 ? -8 : 0),
		    joueur.getVitesse().getY());
	    left = true;
	    // }
	} else if (touche == KeyEvent.VK_RIGHT) {
	    // direction.setText("right");
	    // if (!right)
	    // {
	    joueur.setVitesse((joueur.getVitesse().getX() == 0 ? 8 : 0), joueur
		    .getVitesse().getY());
	    right = true;
	    // }
	} else if (touche == KeyEvent.VK_DOWN) {
	    // direction.setText("down");
	    // if (!down)
	    // {
	    joueur.setVitesse(joueur.getVitesse().getX(), (joueur.getVitesse()
		    .getY() == 0 ? 8 : 0));
	    down = true;
	    // }
	}
	if (touche == KeyEvent.VK_S) {
	    joueur.setTypeFrappe(Joueur.TypeFrappe.TOUCHE_ENFONCEE);
	    // la raquette bouge mais la frappe n'est prise en compte que si on
	    // relache la touche
	}

	if (touche == KeyEvent.VK_D) {
	    joueur.setTypeFrappe(Joueur.TypeFrappe.TOUCHE_ENFONCEE); // la
	    // la raquette bouge mais la frappe n'est prise en compte que si on
	    // relache la touche
	}
    }

    public void toucheRelachee(int touche) {
	if (touche == KeyEvent.VK_UP) {
	    joueur.setVitesse(joueur.getVitesse().getX(), 0);
	    // up = false;
	    // direction.setText(" ");
	} else if (touche == KeyEvent.VK_LEFT) {
	    joueur.setVitesse(0, joueur.getVitesse().getY());
	    // left = false;
	    // direction.setText(" ");
	} else if (touche == KeyEvent.VK_RIGHT) {
	    joueur.setVitesse(0, joueur.getVitesse().getY());
	    // right = false;
	    // direction.setText(" ");
	} else if (touche == KeyEvent.VK_DOWN) {
	    joueur.setVitesse(joueur.getVitesse().getX(), 0);
	    // down = false;
	    // direction.setText(" ");
	}
	if (touche == KeyEvent.VK_S) {
	    joueur.setTypeFrappe(Joueur.TypeFrappe.FRAPPE_HAUTE);
	}
	if (touche == KeyEvent.VK_D) {
	    joueur.setTypeFrappe(Joueur.TypeFrappe.FRAPPE_BASSE);
	}
    }

    // public void keyTyped(KeyEvent evt){}

    public void update() {
	for (int i = 0; i < 4; i++)
    	{
    		joueur = (Joueur)fenetre.getListObjet().get(i);
    		gererCollision();
    		Service();
    	}
    	joueur = (Joueur)fenetre.getListObjet().get(0);
        
        for (Iterator<ObjetControlable> iter = fenetre.getListObjet()
		.iterator(); iter.hasNext();) {
	    ((ObjetControlable) iter.next()).seDeplacer();
	}
	Service();
    }

    public void notifier() {

	// Graphics g = ardoise.getGraphics();
	// g.setColor(Color.green);
	// g.fillRect(0, 0, 600, 400);
	// g.clearRect(0, 0, 600, 400);
	// joueur.seDessiner();
	update();
	fenetre.repaint();

	// balle.seDeplacer();
	// balle.seDessiner(ardoise);
    }

    public void initialiserPoint() {
	throw new UnsupportedOperationException();
    }

    public void gererCollision() {
	boolean frappe = false;
	int newVitesseY;
	if ((joueur.getTypeFrappe() == Joueur.TypeFrappe.FRAPPE_HAUTE)
		| (joueur.getTypeFrappe() == Joueur.TypeFrappe.FRAPPE_BASSE)) {
	    if (balle.getPosition().getZ() <= 15) {
		if (joueur.getLimiteFrappe().contains(
			balle.getPosition().getX(), balle.getPosition().getY())) {
		    if (joueur.getTypeFrappe() == Joueur.TypeFrappe.FRAPPE_BASSE) {
			if (!this.service) {
			    newVitesseY = (int) (balle.getVitesse().getY() + (balle
				    .getPosition().getY()
				    - joueur.getLimiteFrappe().getY() - 10));
			    balle
				    .setVitesse(
					    -balle.getVitesse().getX()
						    + (joueur.getCote() == Joueur.Cote.DROITE ? -5
							    : 5), newVitesseY,
					    6); // balle.getVitesse().getZ()
			    // - 3
			    // balle.getVitesse().setX(-balle.getVitesse().getX());
			    // balle.getVitesse().setZ(0);
			} else {
			    newVitesseY = (int) ((balle.getPosition().getY()
				    - joueur.getLimiteFrappe().getY() - 10));
			    balle
				    .setVitesse(
					    this.joueur.getCote() == Joueur.Cote.DROITE ? -19
						    : 19, newVitesseY, 7); // (this.joueur.getService()
			    // ==
			    // Joueur.Service.SERVICE_HAUT
			    // ?
			    // 5:
			    // -5)
			    this.service = false;
			    this.joueur
				    .setService(joueur.getService() == main.objet.Joueur.Service.SERVICE_HAUT ? Joueur.Service.SERVEUR_HAUT
					    : main.objet.Joueur.Service.SERVEUR_BAS);

			}
		    } else {
			if (!this.service) {
			    newVitesseY = (int) (balle.getVitesse().getY() + (balle
				    .getPosition().getY()
				    - joueur.getLimiteFrappe().getY() - 10));
			    balle
				    .setVitesse(
					    -balle.getVitesse().getX()
						    + (joueur.getCote() == Joueur.Cote.DROITE ? 3
							    : -3), newVitesseY,
					    9); // balle.getVitesse().getZ()
			    // + 3
			    // balle.getVitesse().setZ(9);
			} else {
			    newVitesseY = (int) ((balle.getPosition().getY()
				    - joueur.getLimiteFrappe().getY() - 10));
			    balle
				    .setVitesse(
					    this.joueur.getCote() == Joueur.Cote.DROITE ? -11
						    : 11, newVitesseY, 12); // (this.joueur.getService()
			    // ==
			    // Joueur.Service.SERVICE_HAUT
			    // ?
			    // 5:
			    // -5)
			    this.service = false;
			    this.joueur
				    .setService(joueur.getService() == main.objet.Joueur.Service.SERVICE_HAUT ? Joueur.Service.SERVEUR_HAUT
					    : main.objet.Joueur.Service.SERVEUR_BAS);

			}
		    }
		    frappe = true;
		    balle.setOut(false);
		    balle.setRebond(0);
		    joueur.getEquipe().setFrappe(true);

		}
	    }
	    joueur.setTypeFrappe(Joueur.TypeFrappe.NE_FRAPPE_PAS);

	}

    }

    public void Service() {
	if ((this.joueur.getService() == Joueur.Service.SERVICE_BAS)
		| (this.joueur.getService() == Joueur.Service.SERVICE_HAUT)) {
	    if ((this.joueur.getTypeFrappe() == Joueur.TypeFrappe.NE_FRAPPE_PAS)
		    & (!this.service)) {
		if (this.joueur.getCote() == Joueur.Cote.GAUCHE) {
		    this.balle.setPosition(
			    this.joueur.getPosition().getX() + 5, this.joueur
				    .getPosition().getY() + 11, 0);
		} else {
		    this.balle.setPosition(this.joueur.getPosition().getX(),
			    this.joueur.getPosition().getY() - 6, 0);
		}
		this.balle.setVitesse(0, 0, 0);
	    } else if ((this.joueur.getTypeFrappe() == Joueur.TypeFrappe.TOUCHE_ENFONCEE)
		    & !this.service) {
		this.service = true;
		this.balle.setVitesse(0, 0, 10);
	    }
	}

    }

    @Override
    public void keyPressed(KeyEvent e) {
	toucheAppuyee(e.getKeyCode());
	
    }

    @Override
    public void keyReleased(KeyEvent e) {
	toucheRelachee(e.getKeyCode());
	
    }

    @Override
    public void keyTyped(KeyEvent e) {
	// TODO Auto-generated method stub
	
    }
}
